#ifndef JABSTRACTIO_H
#define JABSTRACTIO_H

#ifdef UNICODE
# undef UNICODE
#endif

///////////////////
/// 抽象IO
///////////////////
#include <JXQCore/JXQGlobal>
#include <JXQCore/JMessage>
#include <JXQCore/JString>
#include <JXQCore/JFlags>

#ifdef _MSC_VER
# pragma warning(disable:26812)
#endif

namespace JXQ
{

class JAbstractIOPrivate;

enum IOErrno : int
{
	IsNotOpen = 1,
	NoExist,
	NoPermissions,
	InvalidParamete,
	Busy,
};

class JXQLIB_EXPORT JAbstractIO
{
	J_MESSAGE(readyRead, JAbstractIO*)

protected:
	JAbstractIO();

public:
	virtual ~JAbstractIO() = 0;

	enum OpenModeFlag
	{
		NotOpen = 0x0000,
		ReadOnly = 0x0001,
		WriteOnly = 0x0002,
		ReadWrite = ReadOnly | WriteOnly,
		Append = 0x0004,
		Truncate = 0x0008,
		Text = 0x0010,
		Unbuffered = 0x0020, //无缓冲
		CreateOnly = 0x0040, //只创建不打开
		DoNotCreate = 0x0080 //如果文件不存在则打开失败
	};
	J_DECLARE_FLAGS(OpenMode, OpenModeFlag)

	virtual bool open(OpenMode mode);
	virtual bool close();

	bool isOpen() const;
	OpenMode openMode() const;
	virtual void setOpenMode(OpenMode mode, bool flag = true);

public:
	int64_t read(void *buffer, int64_t bufSize);
	virtual JString readLine();
	virtual JString readAll();

public:
	int64_t write(const JString &buffer);
	int64_t write(const char *buffer);
	int64_t write(const void *buffer, int64_t bufSize);

public:
	inline bool getChar(char &c);
	char getChar();
	inline bool putChar(const char &c);
	virtual int64_t ioctl(unsigned int, void * = nullptr) {return 0;}

public:
	enum BufferMode
	{
		FullBuffer,
		LineBuffer
	};
	virtual void setBufferMode(BufferMode mode);
	BufferMode bufferMode() const;

	virtual void setBufferSize(int64_t size);
	virtual void flush();
	virtual bool waitForReadyRead(int msecs = -1);

public:
	enum SeekWhence
	{
		SeekSet,
		SeekCur,
		SeekEnd,
	};
	virtual int64_t seek(SeekWhence whence, int64_t offset);
	inline bool reset();
	inline bool atEnt();
	virtual int64_t tell() const;

public:
	virtual int64_t bytesAvailable() const {return 0;} //可读缓冲区大小
	virtual int64_t size() const;

protected:
	virtual int64_t virtualRead(int64_t bufSize, void *buffer) = 0;
	virtual int64_t virtualWrite(int64_t bufSize, const void *buffer) = 0;

protected:
	void setErrno(int err);

public:
	int lastErrno() const;
	JString lastError() const;

protected:
	J_DISABLE_COPY(JAbstractIO)
	friend class JAbstractIOPrivate;
	JAbstractIO(JAbstractIOPrivate *d_ptr);
	JAbstractIOPrivate *d_ptr;
};

inline int64_t JAbstractIO::seek(SeekWhence, int64_t)
{
	return 0;
}

inline bool JAbstractIO::reset()
{
	return seek(SeekSet, 0) >= 0;
}

inline bool JAbstractIO::atEnt()
{
	return seek(SeekEnd, 0) >= 0;
}

inline int64_t JAbstractIO::tell() const
{
	return 0;
}

inline int64_t JAbstractIO::size() const
{
	return bytesAvailable();
}

} //namespace JXQ

J_DECLARE_OPERATORS_FOR_FLAGS(JXQ::JAbstractIO::OpenMode)


#endif //JABSTRACTIO_H
